﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
using System.Threading;
using System.Windows.Media.Imaging;
using WMSSoft.Lib.Basic;
using WMSSoft.Lib.Enums;

namespace WMSSoft.Lib.WinKStart
{
    /// <summary>
    /// Class to read System - Control - Item from Registry and Administrative Tools from StartMenu
    /// </summary>
    public class SystemControlItemsReader
    {
        private string m_SystemControlItems_RegistryNode = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ControlPanel\NameSpace";
        private string m_PathAdministrativeTools = System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu), "Programs");
        private string m_AdministrativeToolspPath = "";
        private cStartmenuItem m_RootSystemControlItem = null;
        private cStartmenuItem m_ThreadSysteemControlItem = null;

        private const string SYSTEM_CONTROL_PANEL_GROUP_KEY = "System.panSystemControlPanelGroup_";
        private const string GUID_EXPLORER_CLASS_ADMINISTRATIVE_TOOLS = "{D20EA4E1-3957-11d2-A40B-0C5020524153}";
        private const string ADMINISTRATIVE_TOOLS_PATH = @"Programs\Administrative Tools";

        public event EventHandler UpdateMenuItems;

        /// <summary>
        /// Create a new Instance
        /// </summary>
        public SystemControlItemsReader()
        {
            try
            {
                m_AdministrativeToolspPath = System.Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu); ;
                m_AdministrativeToolspPath = System.IO.Path.Combine(m_AdministrativeToolspPath, ADMINISTRATIVE_TOOLS_PATH);

                m_RootSystemControlItem = new cStartmenuItem("SYSTEMCONTROLITENROOT", "SystemControlItens", eLinkExecutionTypes.Program, "", eExecutionProcedure.Unknown,
                                                             eItemType.Root, "", null, null, "", "", "", "");
                //Load Systems ControlItems
                LoadControlItems();
            }
            catch (Exception Ex)
            {
                throw new Exception("Error while initialising SystemControlItemsReader!", Ex);
            }
        }

        public SystemControlItemsReader(cStartmenuItem Parent)
        {
            try
            {
                m_AdministrativeToolspPath = System.Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu); ;
                m_AdministrativeToolspPath = System.IO.Path.Combine(m_AdministrativeToolspPath, ADMINISTRATIVE_TOOLS_PATH);

                m_RootSystemControlItem = Parent;
                //Load Systems ControlItems
                LoadControlItems();
            }
            catch (Exception Ex)
            {
                throw new Exception("Error while initialising SystemControlItemsReader!", Ex);
            }
        }

        /// <summary>
        /// Get or Set the SystemControlItems Root
        /// </summary>
        public cStartmenuItem RootSystemControlItem
        {
            get { return m_RootSystemControlItem; }
            set { m_RootSystemControlItem = value; }
        }

        public void LoadControlItems()
        {
            try
            {
                m_ThreadSysteemControlItem = m_RootSystemControlItem;
                Thread m_StartMenuReader_Thread = new Thread(ThreadMethode_LoadControlItems);
                m_StartMenuReader_Thread.Start();
            }
            catch (Exception Ex)
            {

            }
        }

        private void ThreadMethode_LoadControlItems()
        {
            try
            {
                m_PathAdministrativeTools = System.IO.Path.Combine(m_PathAdministrativeTools, "administrative tools");
                //Use HKEY_LOCAL_MACHINE
                RegistryKey HKey = Registry.LocalMachine.OpenSubKey(m_SystemControlItems_RegistryNode);
                RegistryKey HKeyNameSpace = null;
                RegistryKey HKeyShellCommand = null;

                string[] ControlPanelKeyNames = HKey.GetSubKeyNames();
                string[] SystemControlItemSubKeyNames = null;
                string SystemControlName = "";
                string sApplicationName = "";
                string sControlPanelCategories = "";
                string stmpPanelCategory = "";
                string sApllicationExecutable = "control.exe";
                string sApplicationArguments = "";

                cStartmenuItem SystemControlItem = null;
                //Process each NameSpace
                foreach (string Item in ControlPanelKeyNames)
                {
                    if (Item.Substring(0, 1) == "{")
                    {
                        SystemControlName = "";
                        SystemControlName = (String)HKey.OpenSubKey(Item).GetValue("");
                        HKeyNameSpace = null;
                        SystemControlItemSubKeyNames = null;
                        //Open Registry Node for this System Control Item
                        HKeyNameSpace = Registry.ClassesRoot.OpenSubKey(@"CLSID\" + Item);
                        //Read all SubKeysnames
                        SystemControlItemSubKeyNames = HKeyNameSpace.GetSubKeyNames();
                        //load language specific System Control Item Name
                        SystemControlName = Shell.Shell_helpers.LoadMuiStringValue(HKeyNameSpace, "LocalizedString");
                        //if here is no localized Name, use origin
                        if (SystemControlName == null || SystemControlName.Length == 0) SystemControlName = (String)HKey.OpenSubKey(Item).GetValue("");
                        //read the Application Name, this is used to Start System Control Item
                        sApplicationName = (string)HKeyNameSpace.GetValue("System.Applicationname");
                        //Read Categories to add control item
                        sControlPanelCategories = Convert.ToString(HKeyNameSpace.GetValue("System.ControlPanel.Category"));
                        if (sControlPanelCategories == null || sControlPanelCategories.Length == 0) sControlPanelCategories += "0";
                        //Load the Icon for this System Control Item
                        System.Drawing.Icon ItemIcon = Shell.Shell_helpers.LoadRegistryDefaultIcon(HKeyNameSpace);
                        //BitmapImage myBImg = WMSSoft.Lib.Basic.basic_GraphicHelpers.GetWPFImageFromIcon(Shell.Shell_helpers.LoadRegistryDefaultIcon(HKeyNameSpace));

                        if (SystemControlName != null && SystemControlName.Length > 0)
                        {
                            //which command is needed to start item
                            if (sApplicationName != null)
                            {
                                sApllicationExecutable = "control.exe";
                                sApplicationArguments = "-Name " + sApplicationName;
                            }
                            else
                            {
                                if (HKeyNameSpace.OpenSubKey(@"Shell\Open\Command") != null)
                                {
                                    HKeyShellCommand = HKeyNameSpace.OpenSubKey(@"Shell\Open\Command");
                                    sApllicationExecutable = (string)HKeyShellCommand.GetValue("");
                                    sApplicationArguments = "";
                                }
                            }
                            //Create a new StartmenuItem
                            SystemControlItem = new cStartmenuItem(Item, WMSSoft.Lib.Basic.LanguageStrings.GetText(SystemControlName), eLinkExecutionTypes.Program, sApllicationExecutable,
                                                                   eExecutionProcedure.Unknown, eItemType.Link, "", ItemIcon,
                                                                   m_ThreadSysteemControlItem, sApplicationArguments, "", "", "");

                            string[] ControlPanelCategories = sControlPanelCategories.Split(new Char[] { ',' });
                            //Add this item to each category given from registry
                            foreach (string CategoryItem in ControlPanelCategories)
                            {
                                stmpPanelCategory = CategoryItem;

                                if (stmpPanelCategory == "4")
                                    stmpPanelCategory = "2";
                                else if (stmpPanelCategory == "10")
                                    stmpPanelCategory = "5";
                                else if (stmpPanelCategory == "11")
                                    stmpPanelCategory = "0";


                                //Add Item to Parent
                                if (m_RootSystemControlItem != null && ControlItemIsVisible(HKeyNameSpace) == true)
                                    ((cStartmenuItem)m_ThreadSysteemControlItem.ChildItems[SYSTEM_CONTROL_PANEL_GROUP_KEY.ToUpper() + stmpPanelCategory]).AddChild(SystemControlItem);

                            }
                        }
                    }
                }
                //add administrative tools to system tabpage if setting is on
                if (UserSettingsReader.SystemControlSettings.ShowAdministraiveTools == true)
                {
                    //TODO: read administrative tools
                    cStartmenuReader.SearchStartmenuItemsRecursiv(m_AdministrativeToolspPath, 
                                                                  ((cStartmenuItem)m_ThreadSysteemControlItem.ChildItems[SYSTEM_CONTROL_PANEL_GROUP_KEY.ToUpper() + "ADMINISTRATIVETOOLS"])); 
                    
                    //SYSTEM.PANSYSTEMCONTROLPANELGROUP_{D20EA4E1-3957-11d2-A40B-0C5020524153}
                }
            }
            catch (Exception Ex)
            {
                WMSSoft.Lib.Basic.CMessagelogging.AppendMessage("Error while process systemcontrolitems!", Ex, Basic.EMessageTypes.Error);
            }
            finally
            {
                m_RootSystemControlItem = m_ThreadSysteemControlItem;
                if (UpdateMenuItems != null) UpdateMenuItems(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// Read the Property if current system control item is visible for the user
        /// </summary>
        /// <param name="Key">System Control Item Registry Node</param>
        /// <returns>True if visible otherwise false</returns>
        private bool ControlItemIsVisible(RegistryKey Key)
        {
            try
            {
                RegistryKey DefaultIcon = Key.OpenSubKey("DefaultIcon");

                string FileName = (string)DefaultIcon.GetValue("");
                FileName = System.IO.Path.GetFileName(FileName);
                RegistryKey DontLoad = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Control Panel\Don't load");
                if (DontLoad.GetValue(FileName.ToLower()) == null)
                    return true;
                else
                    return false;
            }
            catch (Exception Ex)
            {
                WMSSoft.Lib.Basic.CMessagelogging.AppendMessage("Error while process systemcontrolitem!", Ex, Basic.EMessageTypes.Error);
                return false;
            }
        }

        private void LoadSystemControlPanelGroups()
        {
            try
            {
                cStartmenuItem CategoryItem = null;
                //SystemControl Category "All Control Panel Items"
                CategoryItem = new cStartmenuItem(SYSTEM_CONTROL_PANEL_GROUP_KEY + "0", "All Control Panel Items", eLinkExecutionTypes.Unknown,
                                                                 "", eExecutionProcedure.Unknown, eItemType.Folder, "", null, m_RootSystemControlItem, 
                                                                 "", "", "", "");
                m_RootSystemControlItem.AddChild(CategoryItem);
                CategoryItem = null;
                ////SystemControl Category "Appearance and Personalization"
                //CategoryItem = new cStartmenuItem(SYSTEM_CONTROL_PANEL_GROUP_KEY + "1", "Appearance and Personalization", eLinkExecutionTypes.Unknown,
                //                                                 "", eExecutionProcedure.Unknown, eItemType.Folder, "", null, m_RootSystemControlItem,
                //                                                 "", "", "", "");
                //m_RootSystemControlItem.AddChild(CategoryItem);
                //CategoryItem = null;
                //SystemControl Category "Hardware and Sound"
                CategoryItem = new cStartmenuItem(SYSTEM_CONTROL_PANEL_GROUP_KEY + "2", "Hardware and Sound", eLinkExecutionTypes.Unknown,
                                                                 "", eExecutionProcedure.Unknown, eItemType.Folder, "", null, m_RootSystemControlItem,
                                                                 "", "", "", "");
                m_RootSystemControlItem.AddChild(CategoryItem);
                CategoryItem = null;
                //SystemControl Category "Network and Internet"
                CategoryItem = new cStartmenuItem(SYSTEM_CONTROL_PANEL_GROUP_KEY + "3", "Network and Internet", eLinkExecutionTypes.Unknown,
                                                                 "", eExecutionProcedure.Unknown, eItemType.Folder, "", null, m_RootSystemControlItem,
                                                                 "", "", "", "");
                m_RootSystemControlItem.AddChild(CategoryItem);
                CategoryItem = null;
                //SystemControl Category "Sounds, Speech, and Audio Devices" //no longer used, use in category 2
                CategoryItem = new cStartmenuItem(SYSTEM_CONTROL_PANEL_GROUP_KEY + "4", "Sounds, Speech, and Audio Devices", eLinkExecutionTypes.Unknown,
                                                                 "", eExecutionProcedure.Unknown, eItemType.Folder, "", null, m_RootSystemControlItem,
                                                                 "", "", "", "");
                m_RootSystemControlItem.AddChild(CategoryItem);
                CategoryItem = null;
                //SystemControl Category "System and Security"
                CategoryItem = new cStartmenuItem(SYSTEM_CONTROL_PANEL_GROUP_KEY + "5", "System and Security", eLinkExecutionTypes.Unknown,
                                                                 "", eExecutionProcedure.Unknown, eItemType.Folder, "", null, m_RootSystemControlItem,
                                                                 "", "", "", "");
                m_RootSystemControlItem.AddChild(CategoryItem);
                CategoryItem = null;
                //SystemControl Category "Clock, Language, and Region"
                CategoryItem = new cStartmenuItem(SYSTEM_CONTROL_PANEL_GROUP_KEY + "6", "Clock, Language, and Region", eLinkExecutionTypes.Unknown,
                                                                 "", eExecutionProcedure.Unknown, eItemType.Folder, "", null, m_RootSystemControlItem,
                                                                 "", "", "", "");
                m_RootSystemControlItem.AddChild(CategoryItem);
                CategoryItem = null;
                //SystemControl Category "Ease of Access"
                CategoryItem = new cStartmenuItem(SYSTEM_CONTROL_PANEL_GROUP_KEY + "7", "Ease of Access", eLinkExecutionTypes.Unknown,
                                                                 "", eExecutionProcedure.Unknown, eItemType.Folder, "", null, m_RootSystemControlItem,
                                                                 "", "", "", "");
                m_RootSystemControlItem.AddChild(CategoryItem);
                CategoryItem = null;
                //SystemControl Category "Programs"
                CategoryItem = new cStartmenuItem(SYSTEM_CONTROL_PANEL_GROUP_KEY + "8", "Programs", eLinkExecutionTypes.Unknown,
                                                                 "", eExecutionProcedure.Unknown, eItemType.Folder, "", null, m_RootSystemControlItem,
                                                                 "", "", "", "");
                m_RootSystemControlItem.AddChild(CategoryItem);
                CategoryItem = null;
                //SystemControl Category "User Accounts and Family Safety" //in Domain calles "User Accounts"
                CategoryItem = new cStartmenuItem(SYSTEM_CONTROL_PANEL_GROUP_KEY + "9", "User Accounts and Family Safety", eLinkExecutionTypes.Unknown,
                                                                 "", eExecutionProcedure.Unknown, eItemType.Folder, "", null, m_RootSystemControlItem,
                                                                 "", "", "", "");
                m_RootSystemControlItem.AddChild(CategoryItem);
                CategoryItem = null;
                //SystemControl Category "Security" //no longer used items now in category 5
                CategoryItem = new cStartmenuItem(SYSTEM_CONTROL_PANEL_GROUP_KEY + "10", "Security", eLinkExecutionTypes.Unknown,
                                                                 "", eExecutionProcedure.Unknown, eItemType.Folder, "", null, m_RootSystemControlItem,
                                                                 "", "", "", "");
                m_RootSystemControlItem.AddChild(CategoryItem);
                CategoryItem = null;
                //SystemControl Category "Mobile PC" Items now in Category 0
                CategoryItem = new cStartmenuItem(SYSTEM_CONTROL_PANEL_GROUP_KEY + "11", "Mobile PC", eLinkExecutionTypes.Unknown,
                                                                 "", eExecutionProcedure.Unknown, eItemType.Folder, "", null, m_RootSystemControlItem,
                                                                 "", "", "", "");
                m_RootSystemControlItem.AddChild(CategoryItem);
                CategoryItem = null;
            }
            catch (Exception Ex)
            {
                throw new Exception("Unable to add Sytem control Panel groups!", Ex);
            }
        }
    }
}
